package com.egao.common.module.counsel.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Console;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.egao.common.component.minio.config.MinioBucket;
import com.egao.common.component.minio.service.MinioService;
import com.egao.common.component.wechat.WeChatUtils;
import com.egao.common.core.exception.BusinessException;
import com.egao.common.core.utils.CoreUtil;
import com.egao.common.core.web.JsonResult;
import com.egao.common.core.web.PageParam;
import com.egao.common.core.web.PageResult;
import com.egao.common.module.counsel.CounselConstants;
import com.egao.common.module.counsel.entity.Counsel;
import com.egao.common.module.counsel.entity.CounselStudent;
import com.egao.common.module.counsel.enums.CounselTypeEnum;
import com.egao.common.module.counsel.mapper.CounselStudentMapper;
import com.egao.common.module.counsel.result.CounselResult;
import com.egao.common.module.counsel.service.CounselService;
import com.egao.common.module.counsel.service.CounselStudentService;
import com.egao.common.module.student.entity.Student;
import com.egao.common.module.student.service.StudentService;
import com.egao.common.module.system.service.EmailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author lym
 * @date 2022/1/24 17:11
 */
@Service
public class CounselStudentServiceImpl extends ServiceImpl<CounselStudentMapper, CounselStudent> implements CounselStudentService {

    @Autowired
    private CounselService counselService;

    @Autowired
    private StudentService studentService;

    @Autowired
    private EmailService emailService;

    @Autowired
    private MinioService minioService;

    @Override
    public List<CounselStudent> listPage(PageParam<CounselStudent> pageParam) {
        List<CounselStudent> counselStudentList = baseMapper.listPage(pageParam);
        for (CounselStudent counselStudent : counselStudentList) {
            counselStudent.setResumePreview(minioService.getPreSignedObjectUrl(MinioBucket.MINIO_COUNSEL, counselStudent.getResumeUrl()));
            counselStudent.setBsPreview(minioService.getPreSignedObjectUrl(MinioBucket.MINIO_COUNSEL, counselStudent.getBsUrl()));
        }
        return counselStudentList;
    }

    @Override
    public JsonResult cancel(CounselStudent counselStudent) {
        Counsel counsel = counselService.getById(counselStudent.getCounselId());
        if (CounselConstants.COUNSEL_STATE_CANCEL.equals(counsel.getState())) {
            throw new BusinessException("咨询师已取消该预约");
        }

        if (CounselConstants.STUDENT_STATE_CANCEL.equals(counselStudent.getState())) {
            throw new BusinessException("已取消预约");
        }

        if (CounselConstants.STUDENT_STATE_PROMISE.equals(counselStudent.getState())) {
            throw new BusinessException("已赴约无法取消");
        }

        if (System.currentTimeMillis() >= counsel.getCounselDate().getTime()) {
            throw new BusinessException("预约时间当天及以后不可取消");
        }

        counselStudent.setState(CounselConstants.STUDENT_STATE_CANCEL);
        counselStudent.setCancelDate(new Date());
        if (updateById(counselStudent)) {
            return JsonResult.ok();
        }

        return JsonResult.error();
    }

    @Override
    public JsonResult saveCounselStudent(CounselStudent counselStudent) {
        Counsel counsel = counselService.getById(counselStudent.getCounselId());
        if (counsel == null) {
            throw new BusinessException("该预约已失效");
        }

        if (CounselConstants.COUNSEL_STATE_CANCEL.equals(counsel.getState())) {
            throw new BusinessException("咨询师已取消该预约");
        }

        if (System.currentTimeMillis() >= counsel.getCounselDate().getTime()) {
            throw new BusinessException("该咨询预约时间已过");
        }

        CounselStudent old = baseMapper.selectOne(new LambdaQueryWrapper<CounselStudent>()
                .eq(CounselStudent::getCounselId, counselStudent.getCounselId())
                .ne(CounselStudent::getState, CounselConstants.STUDENT_STATE_CANCEL)
                .last("limit 1")
        );

        if (old != null) {
            throw new BusinessException("抱歉您来晚了，该咨询已被预约");
        }

        counselStudent.setState(CounselConstants.STUDENT_STATE);
        counselStudent.setStudentFeedback(CounselConstants.FEEDBACK_STATE_NON);
        counselStudent.setTeacherFeedback(CounselConstants.FEEDBACK_STATE_NON);
        if (baseMapper.insert(counselStudent) > 0) {
            return JsonResult.ok("预约成功");
        }

        return JsonResult.error();
    }

    @Override
    public JsonResult importCounsel(MultipartFile file, Integer id) {
        Counsel counsel = counselService.getById(id);

        Map<Integer, String> resultMap = new HashMap<>();

        List<CounselResult> counselResults = new ArrayList<>();

        try {
            // 读取Excel
            int startRow = 1;
            ExcelReader reader = ExcelUtil.getReader(file.getInputStream(), 0);
            reader.setIgnoreEmptyRow(false);
            List<List<Object>> list = reader.read(startRow);
            List<Integer> studentIds = new ArrayList<>();
            for(int i = 0; i < list.size(); i++) {
                List<Object> objects = list.get(i);
                if (objects.isEmpty()) {
                    counselResults.add(new CounselResult(i + 2, "学号不能为空！"));
                    continue;
                }
                String xh = String.valueOf(objects.get(0));
                Student student = studentService.getByXh(xh);
                if (Objects.isNull(student)) {
                    counselResults.add(new CounselResult(i + 2, "学号（" + xh + "）不存在！"));
                    continue;
                }
                studentIds.add(student.getId());
            }
            if(!counselResults.isEmpty()) {
                return JsonResult.error().setData(counselResults);
            }
            List<CounselStudent> counselStudentList = new ArrayList<>();

            for (Integer studentId : studentIds) {
                CounselStudent counselStudent = new CounselStudent();
                counselStudent.setCounselId(counsel.getId());
                counselStudent.setCounselTeacherId(counsel.getCounselTeacherId());
                counselStudent.setStudentId(studentId);
                counselStudent.setState(CounselConstants.COUNSEL_STATE);
                counselStudent.setTitle(CounselTypeEnum.getByValue(counsel.getCounselType()).getLabel());
                counselStudentList.add(counselStudent);
            }

            if (!saveBatch(counselStudentList)) {
                throw new BusinessException("导入失败");
            }
            return JsonResult.ok("导入完成");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return JsonResult.error("导入失败");
    }

    @Override
    public void push() {
        Date today = DateUtil.date();
        Date nextDay = DateUtil.offsetDay(today, 1);
        Date nextDayWithSpecificTime = DateUtil.beginOfDay(nextDay);

        PageParam<CounselStudent> pageParam = new PageParam<>();
        pageParam.put("counselDate", nextDayWithSpecificTime);
        pageParam.setSize(-1);
        List<CounselStudent> counselStudents = listPage(pageParam);

        for (CounselStudent c : counselStudents) {
            try {
                String content = "您预约的" + c.getCounselDate() + " " + c.getCounselTime() + "的咨询会将在明天开始，请按时参加。";
                emailService.sendTextEmail("预约咨询取消通知", content, new String[]{c.getEmail()});
                // 发生企业号消息
                WeChatUtils.push(new String[]{c.getXh()}, content);
            } catch (Exception e) {
                Console.error(e, "咨询师取消发送通知异常");
            }
        }
    }

    @Override
    public List<CounselStudent> listBigData(String startDate, String endDate) {
        return baseMapper.listBigData(startDate, endDate);
    }
}
